package com.hyt.it.ogt.kq.service.gov.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.entity.TaskArea;
import com.hyt.it.ogt.kq.service.gov.model.entity.TaskMockRoomData;
import com.hyt.it.ogt.kq.service.gov.model.entity.TimeRoom;
import com.hyt.it.ogt.kq.service.gov.model.param.PageRoomPackageParam;
import com.hyt.it.ogt.kq.service.gov.model.vo.RoomPackageVO;
import com.hyt.it.ogt.kq.service.gov.model.vo.roomdata.UnArrangeRoomTimeInfoVO;
import com.hyt.it.ogt.kq.service.gov.service.*;
import com.hyt.it.ogt.kq.common.gov.utils.HuaweiCloudObsUtil;
import com.hyt.it.ogt.kq.common.gov.utils.TextUtil;
import com.hyt.loginfo.service.IBaseLoginService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;


/**
 * 考务包
 *
 * @author 刘恒活
 * @since 2021/9/6 14:15
 */
@Slf4j
@Service
public class RoomDataServiceImpl implements IRoomDataService {

    @Resource
    private ITimeRoomService iTimeRoomService;

    @Resource
    private ITaskAreaService taskAreaService;

    @Resource
    private ITaskService iTaskService;

    @Resource
    private IAsyncService iAsyncService;

    @Resource
    private ITaskMockRoomDataService iTaskMockRoomDataService;

    @Resource
    private IBaseLoginService iBaseLoginService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createByTaskId(String taskId, String version) throws Exception {
        // 通过版本号锁定，不能编排期间解锁变更编排数据
        // 生成前校验，校验是否锁定编排，基础包是否生成，编排表是否有数据
        this.check(taskId);
        //获取机构id
        String officeId = iBaseLoginService.getOfficeId();
        //按场次生成考务包(异步，点击生成后立即返回成功给到前端，前端再通过进度条接口获取生成进度)
        iAsyncService.createRoomData(taskId, officeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createMockRoomDataByTaskId(String taskId) {
        //生成模拟测试考务包前校验
        this.createMockRoomDataCheck(taskId);
        //获取机构id
        String officeId = iBaseLoginService.getOfficeId();
        //生成模拟测试考务包(异步)
        iAsyncService.createMockRoomData(taskId, officeId);
    }

    /**
     * 生成模拟测试考务包前校验
     * @param taskId 考试任务id
     */
    private void createMockRoomDataCheck(String taskId) {
        //获取考试任务基础信息
        Task task = iTaskService.getById(taskId);
        //校验考试任务是否存在
        if (ObjectUtils.isEmpty(task)) {
            //考试任务不存在
            throw new KqException(ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_TASK_NOT_FOUND.getCode(),
                    ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_TASK_NOT_FOUND.getMsg());
        }
        //校验数据锁定状态
        Boolean dataLocked = task.getDataLock();
        if (ObjectUtils.isNotEmpty(dataLocked) && Boolean.FALSE.equals(dataLocked)) {
            //未锁定编排数据，无法生成模拟测试考务包
            throw new KqException(ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_NOT_LOCKED.getCode(),
                    ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_NOT_LOCKED.getMsg());
        }
        //校验模拟测试考务包是否已生成
        if (this.hasMockRoomData(taskId)) {
            //模拟测试考务包已存在
            throw new KqException(ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_ALREADY_EXISTS.getCode(),
                    ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_ALREADY_EXISTS.getMsg());
        }
        //校验是否存在为编排考生的考场
        List<UnArrangeRoomTimeInfoVO> timeRoomList = iTimeRoomService.selectUnArrangeTimeRoomInfo(taskId);
        if (timeRoomList.size() > 0) {
            //存在未编排考生的考场，无法生成模拟测试考务包
            throw new KqException(ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_EMPTY_ROOM_FOUND.getCode(),
                    ResponseCode.CREATE_MOCK_ROOM_DATA_BY_TASK_EMPTY_ROOM_FOUND.getMsg());
        }
    }

    @Override
    public boolean hasMockRoomData(String taskId) {
        Optional<TaskMockRoomData> optional = iTaskMockRoomDataService.lambdaQuery()
                .select(TaskMockRoomData::getId)
                .eq(TaskMockRoomData::getTaskId, taskId)
                .eq(TaskMockRoomData::getDelFlag, false)
                .last("LIMIT 1")
                .oneOpt();
        return optional.isPresent();
    }

    /**
     * 删除考务包
     *
     * @param taskId 任务
     */
    @Override
    public void deleteRoomDataPackageByTaskId(String taskId) {
        LambdaUpdateWrapper<TimeRoom> updateWrapper = Wrappers.<TimeRoom>lambdaUpdate().eq(TimeRoom::getTaskId, taskId)
                .set(TimeRoom::getRoomDataFileId, null);
        iTimeRoomService.update(updateWrapper);
    }

    /**
     * 删除考务包
     *
     * @param timeRoomId 场次Id
     */
    @Override
    public void deleteRoomDataPackageByTimeRoomId(String timeRoomId) {
        LambdaUpdateWrapper<TimeRoom> updateWrapper = Wrappers.<TimeRoom>lambdaUpdate().eq(TimeRoom::getId, timeRoomId)
                .set(TimeRoom::getRoomDataFileId, null);
        iTimeRoomService.update(updateWrapper);
    }

    @Override
    public Page<RoomPackageVO> page(PageRoomPackageParam param) {
        if (TextUtil.isNull(param.getTaskId())) {
            throw new KqException(ResponseCode.ERROR_ROOM_DATA_TASK_ID_IS_NULL.getCode(),
                    ResponseCode.ERROR_ROOM_DATA_TASK_ID_IS_NULL.getMsg());
        }
        Page<RoomPackageVO> roomPackages = iTimeRoomService.getPageRoomPackage(param);
        List<RoomPackageVO> records = roomPackages.getRecords();
        //1.如果考务包数据不为空
        if (TextUtil.isNotNull(records)) {
            Map<String, TaskArea> taskAreaMap = taskAreaService.getTaskAreaMap(param.getTaskId());
            if (!taskAreaMap.isEmpty()) {
                roomPackages.getRecords().forEach(item -> {
                    String path = item.getPath();
                    //2.如果有考务包数据
                    if (TextUtil.isNotNull(path)) {
                        item.setPath(HuaweiCloudObsUtil.getObjectUrl(path));
                    }
                    //3.组装省市县区
                    if (TextUtil.isNotNull(item.getProvince())) {
                        TaskArea province = taskAreaMap.get(item.getProvince());
                        if (TextUtil.isNotNull(province)) {
                            item.setProvinceName(province.getName());
                        }
                    }
                    if (TextUtil.isNotNull(item.getCity())) {
                        TaskArea city = taskAreaMap.get(item.getCity());
                        if (TextUtil.isNotNull(city)) {
                            item.setCityName(city.getName());
                        }
                    }
                    if (TextUtil.isNotNull(item.getDistrict())) {
                        TaskArea district = taskAreaMap.get(item.getDistrict());
                        if (TextUtil.isNotNull(district)) {
                            item.setDistrictName(district.getName());
                        }
                    }
                });
            }

        }
        return roomPackages.setRecords(records);
    }

    /**
     * 生成前校验，校验是否锁定编排，基础包是否生成，编排表是否有数据
     *
     * @param taskId 任务
     */
    private void check(String taskId) {
        Task task = iTaskService.getById(taskId);
        if (task == null || task.getDelFlag()) {
            throw new KqException(ResponseCode.CREATE_ROOM_DATA_TASK_NOT_EXIST.getCode(),
                    ResponseCode.CREATE_ROOM_DATA_TASK_NOT_EXIST.getMsg());
        }
        // 校验任务数据锁定状态(后续版本考虑优化为从缓存中获取状态)
        Boolean dataLock = iTaskService.lambdaQuery().eq(Task::getId, taskId).last("LIMIT 1").one().getDataLock();
        if (!dataLock) {
            throw new KqException(ResponseCode.CREATE_ROOM_DATA_NOT_LOCK_ARRANGED_DATA_EXIST.getCode(),
                    ResponseCode.CREATE_ROOM_DATA_NOT_LOCK_ARRANGED_DATA_EXIST.getMsg());
        }
        if (iTimeRoomService.count(Wrappers.<TimeRoom>lambdaQuery().eq(TimeRoom::getTaskId, taskId)
                .isNotNull(TimeRoom::getRoomDataFileId).eq(TimeRoom::getDelFlag, false)) > 0) {
            throw new KqException(ResponseCode.ROOM_DATA_EXIST.getCode(),
                    ResponseCode.ROOM_DATA_EXIST.getMsg());
        }
        // 正常考场（非备用考场）编排人数为0的考场也生成考务包
        /* 暂不考虑备用考场
        List<UnArrangeRoomTimeInfoVO> timeRoomList = iTimeRoomService.selectUnArrangeTimeRoomInfo(taskId);
        if (timeRoomList.size() > 0) {
            throw new KqException(ResponseCode.EXIST_UN_ARRANGE_TIME_ROOM.getCode(),
                    ResponseCode.EXIST_UN_ARRANGE_TIME_ROOM.getMsg(), timeRoomList);
        }*/
    }
}
